<!-- setup在beforeCreate生命周期开始前就执行了 -->
<!-- 
   不用写import { ref, reactive, onMounted } from 'vue' 
   npm install unplugin-auto-import -D 避免每次都重复书写引入
   并在vite.config.js中进行配置
-->

<script setup>
import { watch } from 'vue';
import List from '../components/List.vue'
import Child from '../components/Child.vue'
import AA from '../components/AA.vue'
import BB from '../components/BB.vue'

// 父传子
let fatherMsg = ref('父组件的数据')
// 子传父
const childMsg = (val) => {
  console.log(val.value)
}
// 父子互传
let num = ref(1)

// 生命周期
onMounted(() => {
  console.log('onMounted');
})

// 响应式数据
// ref定义简单类型 reactive定义引用类型
const obj1 = reactive({
  a: 10,
  b: 2
})
let str = ref('this is string')
let arr = ref([1, 2, 3])
let btn = () => {
  // ref类型下获取引用类型的值要加.value
  arr.value[0] = 666
  str = '1666'
  obj1.a = 1000
}

// 解构赋值
// 将响应式对象中的属性转换为单独的响应式数据，直接解构则变成普通数据
let { a, b } = toRefs(obj1)
console.log(a);

// 计算属性
let msg = ref('这是一个用于测试computed的ref响应数据')
let msgChange = computed(() => {
  return msg.value.slice(1, 5)
})

// watch
let wmsg = ref('watch数据')
let wmsg2 = ref('watch数据2')
let wobj = reactive({
  name: "LiMing",
  subjects: ['语文', '数学']
})

// 可以同时监听多个变量
watch([wmsg, wmsg2], (newval, oldval) => {
  console.log(newval, oldval);
}, {
  // 还没改变前也监听
  immediate: true
})

// 监听对象里的数据变化
// 不能监听reactive定义的整个对象，只能监听其中某个属性，且要用返回值表示
// watch source can only be a getter/effect function, a ref, a reactive object
watch(() => wobj.name, (newval, oldval) => {
  console.log(newval, oldval);
})

// 路由跳转
// useRouter == this.$router
let uses = new useRouter
let go = () => {
  uses.push('/about')
}

// 动态插槽
let slotName = ref('CCC')

// 动态组件
const componentArr = reactive([
  {
    name: '我是组件A',
    // 不可以用字符串形式
    comName: markRaw(AA)
  },
  {
    name: '我是组件B',
    comName: markRaw(BB)
  }
])
let current = reactive({
  comName: componentArr[0].comName
})
const changeComponent = (item) => {
  current.comName = item.comName
}

// mixin 复用
import mixin from '../mixin/mixin.js'
let { numb, fav, favBtn } = mixin()

// provide和inject
let info = ref('root组件的数据')
provide('parentInfo', info)

// vuex
import { useStore } from 'vuex';
let store = useStore()
// 保持数据为响应式
let store_str = computed(() => store.state.str)
const store_btn = () => {
  store.commit('changeStr')
}

// pinia
import { usePinia } from '../store/pinia.js'
import { userStore } from '../store/user.js'
import { storeToRefs } from 'pinia';
const pinia = usePinia()
// 分模块
const user = userStore()

let { pinia_counter, pinia_name, change_pinia_counter } = storeToRefs(pinia)
let { user_age, user_email } = storeToRefs(user)

const changeName = () => {
  // 可以直接修改state的数据
  pinia_name.value = 'Lisa'

  // 批量更新方法
  pinia.$patch(state => {
    state.pinia_counter++
    state.pinia_name = `张${Math.floor(Math.random(10) * 10)}山`
  })
}

const changeCounter = () => {
  pinia.update_counter(666)
}

const pinia_reset = () => {
  pinia.$reset()
}
</script>

<template>
  <div>str:{{ str }}</div>
  <div>arr:{{ arr }}</div>
  <div>obj1:{{ obj1 }}</div>
  <div>
    a:{{ a }}
  </div>
  <div>
    b:{{ b }}
  </div>
  <div>{{ msg }} ==> {{ msgChange }}</div>
  <button type="button" @click="btn">点击修改</button>

  <p style="height: 4px;background-color: #666;margin: 30px;"></p>

  <input type="text" v-model="wmsg">
  <input type="text" v-model="wmsg2">
  <input type="text" v-model="wobj.name">
  <button type="button" @click="go">跳转路由</button>

  <p style="height: 4px;background-color: #666;margin: 30px;"></p>

  <List :msg="fatherMsg" @fn="childMsg"></List>

  <p style="height: 4px;background-color: #666;margin: 30px;"></p>

  <div class="main">
    这是main
  </div>

  <p style="height: 4px;background-color: #666;margin: 30px;"></p>

  <!-- 父子组件双向数据 -->
  <Child v-model:num="num">
    <template #AAA>
      具名插槽
      给插槽A的数据
      #AAA 等同于 v-slot:AAA
    </template>

    <template v-slot="{ data }">
      作用域插槽
      {{ data }}
    </template>

    <template v-slot:BBB>
      具名插槽
      给插槽B的数据
    </template>

    <template #[slotName]>
      动态插槽
      给插槽C的数据
    </template>
  </Child>

  <p style="height: 4px;background-color: #666;margin: 30px;"></p>

  <div>动态组件</div>
  <ul class="tab_list">
    <li @click="changeComponent(item)" v-for="(item, index) in componentArr" :key="index">
      {{ item.name }}
    </li>
  </ul>
  <!-- 此处也不能使用字符串形式，必须通过动态传参 -->
  <component :is="current.comName"></component>

  <p style="height: 4px;background-color: #666;margin: 30px;"></p>

  <div>
    <p>mixin复用，各组件间同时使用数据互不影响，和vuex不同</p>
    {{ numb }}
    {{ fav }}
    <button @click="favBtn">
      {{ fav ? '收藏中...' : '收藏' }}
    </button>
  </div>

  <p style="height: 4px;background-color: #666;margin: 30px;"></p>

  <div>
    <p>{{ store_str }}</p>
    <button @click="store_btn">修改str</button>
  </div>

  <p style="height: 4px;background-color: #666;margin: 30px;"></p>

  <div>
    <p>pinia</p>
    <p>{{ pinia_counter }}</p>
    {{ pinia_name }} <br>
    {{ change_pinia_counter }}
    <button @click="changeName">直接修改名字</button>
    <button @click="changeCounter">调用action</button>
    <button @click="pinia_reset">重置API</button>

    <div>
      分模块
      {{ user_email }}
      {{ user_age }}
    </div>
  </div>
</template>
